<template>
  <DragResize
    v-if="widgetVisible"
    :is-active="!isSelectMode ? widget.active : widget.activeForPicker"
    :data-id="widget.id"
    :widget="widget"
    :parent-w="parentWH.parentW"
    :parent-h="parentWH.parentH"
    :init-rect="widgetRect"
    :minh="0"
    :minw="0"
    :snap-to-grid="true"
    :grid-x="1"
    :grid-y="1"
    :stick-size="5"
    :prevent-active-behavior="true"
    :draggable="widgetDraggable"
    :resizable="widgetResizable"
    :droppable="widgetDroppable"
    :selectable="widgetSelectable"
    :is-locked="widget.isLocked"
    :is-freeze="widget.isFreeze"
    :style="styles"
    class="position-absolute box-sizing-border"
    @clicked="onClicked" @dblclick.native="doubleClickWidget"
    @resizing="onResize" @dragging="onResize"
    @resizestop="stopResize" @dragstop="stopResize">
    <ButtonWidget v-if="['iconTextButton','iconButton'].includes(widget.category)" :widget="widget"></ButtonWidget>
    <TextWidget v-if="widget.category === 'text'" :widget="widget"></TextWidget>
    <IconWidget v-if="widget.category === 'indicator'" :widget="widget"></IconWidget>
    <ProcessorWidget v-if="widget.category === 'processor'" :widget="widget"></ProcessorWidget>
    <LevelWidget v-if=" widget.category === 'level'" :widget="widget"></LevelWidget>
    <InputWidget v-if="widget.category === 'input'" :widget="widget"></InputWidget>
    <InputNumberWidget v-if="widget.category === 'inputNumber'" :widget="widget"></InputNumberWidget>
    <SwitchWidget v-if="widget.category === 'switch'" :widget="widget"></SwitchWidget>
    <SliderWidget v-if="widget.category === 'slider'" :widget="widget"></SliderWidget>
    <DateTime v-if="widget.category === 'dateTime'" :widget="widget"></DateTime>
    <SpeechRecognition v-if="widget.category === 'speechRecognition'" :widget="widget"></SpeechRecognition>
    <MeetingList
	    v-if="widget.type ==='componentFunction' && widget.category === 'meetingList'"
	    :widget="widget"></MeetingList>
    <VideoMatrix v-if="widget.category === 'matrixPage'" :widget="widget"></VideoMatrix>
    <Camera v-if="widget.category === 'cameraPage'" :widget="widget"></Camera>
    <CameraTracking v-if="widget.category === 'cameraTrack'" :widget="widget"></CameraTracking>
    <UrlPlayer v-if="['urlPlayer','cameraView'].includes(widget.category)" :widget="widget"></UrlPlayer>
    <WebView v-if="widget.category === 'webView'" :widget="widget"></WebView>
    <PadRelatedRooms v-if="widget.category === 'padRelatedRooms'" :widget="widget"></PadRelatedRooms>
    <DistributeMatrix v-if="widget.category === 'distributedMatrix'" :widget="widget"></DistributeMatrix>
    <TabBar v-if="widget.category === 'tabBarPage'" :widget="widget" :is-select-mode="isSelectMode"></TabBar>
    <PageView  v-if="widget.category === 'pageView'" :widget="widget" :is-select-mode="isSelectMode"></PageView>
    <SelectInputWidget v-if="widget.category === 'selectInput'" :widget="widget"></SelectInputWidget>
    <PlatformEZlink v-if="widget.category === 'platformEZLink'" :widget="widget"></PlatformEZlink>
    <Carousel v-if="widget.category === 'imageVideoListPlayer'" :widget="widget"></Carousel>
    <ButtonList v-if="widget.category === 'buttonList'" :widget="widget"></ButtonList>
    <DeviceWidgetLayout
	    v-if="widget.category === 'dragLayout'"
	    :widget="widget"
	    :is-multi-mode="isMultiMode"
	    :is-select-mode="isSelectMode"></DeviceWidgetLayout>
    <SipCall v-if="widget.category === 'sipCall'" :widget="widget"></SipCall>
    <Widget
	    v-if="widget.category !== 'dragLayout'"
      v-for="child in widgetChildren"
      :key="child.id"
      :widget="child"
      :is-multi-mode="isMultiMode"
      :is-select-mode="isSelectMode"></Widget>
    <i
      v-if="isMultiMode && widget.active"
      :class="widget.isLocked ? 'icon-shangsuo font-color-danger' : 'icon-qiyong font-color-primary'"
      class="iconfont widget-select-mark"></i>
    <div v-if="showMask" class="widget-mask"></div>
    <div v-for="(line, idx) in widget.snapLine" :key="`snapLine${idx}`"
         :style="{ left: `${line.left || 0}px`, top: `${line.top || 0}px` }"
         :class="line.type === 'h' ? 'snap-line-horizontal' : 'snap-line-vertical'"
         class="snap-line"></div>
    <div v-for="(line, idx) in widget.topLine" :key="`topLine${idx}`"
         :style="{top: `${line.top || 0}px`, left: `${line.left || 0}px`, height: `${line.height || 0}px`}"
         class="space-line space-line-vertical">
      <div class="el-divider__text is-center ver-center">{{line.height || 0}}</div>
    </div>
    <div v-for="(line, idx) in widget.rightLine" :key="`rightLine${idx}`"
         :style="{top: `${line.top || 0}px`, left: `${line.left || 0}px`, width: `${line.width || 0}px`}"
         class="space-line space-line-horizontal">
      <div class="el-divider__text is-center">{{line.width || 0}}</div>
    </div>
    <div v-for="(line, idx) in widget.bottomLine" :key="`bottomLine${idx}`"
         :style="{top: `${line.top || 0}px`, left: `${line.left || 0}px`, height: `${line.height || 0}px`}"
         class="space-line space-line-vertical">
      <div class="el-divider__text is-center ver-center">{{line.height || 0}}</div>
    </div>
    <div v-for="(line, idx) in widget.leftLine" :key="`leftLine${idx}`"
         :style="{top: `${line.top || 0}px`, left: `${line.left || 0}px`, width: `${line.width || 0}px`}"
         class="space-line space-line-horizontal">
      <div class="el-divider__text is-center">{{line.width || 0}}</div>
    </div>
  </DragResize>
</template>

<script>
  import DragResize from '../../DragResize';
  import TextWidget from './Text';
  import ButtonWidget from './Button';
  import IconWidget from './Icon';
  import ProcessorWidget from './Processor';
  import LevelWidget from './level';
  import InputWidget from './Input';
  import SelectInputWidget from './SelectInput.vue';
  import InputNumberWidget from './InputNumber.vue';
  import SwitchWidget from './Switch';
  import SliderWidget from './Slider';
  import DateTime from './DateTime.vue';
  import SpeechRecognition from '../custom/SpeechRecognition';
  import CameraTracking from '../custom/CameraTracking.vue';
  import MeetingList from '../custom/MeetingList';
  import VideoMatrix from '../custom/VideoMatrix.vue';
  import PadRelatedRooms from '../custom/PadRelatedRooms.vue';
  import PlatformEZlink from '../custom/PlatformEZlink.vue';
  import Camera from '../custom/Camera.vue';
  import UrlPlayer from '../custom/UrlPlayer.vue';
  import WebView from '../custom/WebView.vue';
  import DistributeMatrix from '../custom/DistributeMatrix.vue';
  import Carousel from '../custom/Carousel.vue';
  import TabBar from '../atom/TabBar.vue';
  import PageView from '../atom/PageView.vue';
  import ButtonList from '../atom/ButtonList.vue';
	import DeviceWidgetLayout from "@/components/IDE/widget/atom/DeviceWidgetLayout.vue";
  import SipCall from '../custom/SipCall.vue';
  import {deepCopy, formatColor} from '@/utils';
  import {assetBaseUrl} from '@/config/env';
  import {mapState} from 'vuex';
  import {generateWidgetHash, getBasicStyles, WidgetClass, widgetHashKeys} from '@/modules/IDE/widget/atom/widget';
  import {WidgetFactory} from "@/modules/IDE/widgetFactory";

  export default {
    name: 'Widget',
    components: {
      DragResize, TextWidget,
      ButtonWidget, IconWidget, ProcessorWidget, LevelWidget,
      InputWidget, SwitchWidget, SliderWidget, DateTime,
      SpeechRecognition, CameraTracking, MeetingList,
      VideoMatrix, Camera, UrlPlayer, DistributeMatrix, InputNumberWidget, TabBar,
      SelectInputWidget, PadRelatedRooms, WebView, PlatformEZlink, Carousel, ButtonList,
	    DeviceWidgetLayout,PageView,SipCall
    },
    props: {
      widget: {
        type: WidgetClass,
        default: () => {
          return {};
        }
      },
      isMultiMode: {
        type: Boolean,
        default: false
      },
      isSelectMode: {
        type: Boolean,
        default: false
      },
    },
    data() {
      return {
        widgetChangeHandler: () => {
        },
        snapLineTimer: null,
      };
    },
    computed: {
      ...mapState({
	      activeTheme: state => state.ide.activeTheme,
	      curPageType: state => state.ide.curPageType,
	      curPageTypeForPicker: state => state.ide.curPageTypeForPicker,
	      freezeMode: state => state.ide.freezeMode,
      }),
      computedWidget() {
        const widget = {};
        // 过滤出关心变更的属性，并进行深拷贝
        widgetHashKeys.forEach(key => widget[key] = this.widget[key]);
        return widget;
      },
      widgetRect() {
        const {relateSubPageId} = this.widget;
        if (!relateSubPageId) {
          return this.widget.rect;
        } else {
          // 坐标以组件自己的为准，尺寸以组件关联的子页面为准
          const {left, top} = this.widget.rect;
          const subPage = WidgetFactory.getWidgetById(relateSubPageId);
          const {width, height} = subPage.rect;
          return {left, top, width, height};
        }
      },
      widgetVisible() {
        if (this.widget.isDeleted) return false;
        return !this.isSelectMode ? this.widget.display : this.widget.displayForPicker;
      },
      widgetDraggable() {
        if (this.freezeMode) return false;
        if (this.isSelectMode) return false;
        if (this.belongNotMatch) return false;
        return this.widget.draggable;
      },
      widgetResizable() {
        if (this.freezeMode) return false;
        if (this.isSelectMode) return false;
        if (this.belongNotMatch) return false;
        return this.widget.resizable;
      },
      widgetDroppable() {
        if (this.freezeMode) return false;
        if (this.isSelectMode) return false;
        if (this.belongNotMatch) return false;
        return this.widget.droppable;
      },
      widgetSelectable() {
        if (this.belongNotMatch) return false;
        if (this.isSelectMode) return true;
        return this.widget.selectable;
      },
      widgetChildren() {
        const {relateSubPageId} = this.widget;
        const widget = relateSubPageId ? WidgetFactory.getWidgetById(relateSubPageId) : this.widget;
        if (!widget) return [];
        return widget.children || [];
      },
      // 传父组件宽高
      parentWH() {
        const parentWidget = WidgetFactory.getWidgetById(this.widget.parentId) || null;
        return {
          'parentW': parentWidget ? parentWidget.rect.width : 0,
          'parentH': parentWidget ? parentWidget.rect.height : 0
        }
      },
	    belongNotMatch() {
				// 判断组件从属是否匹配，主页中应用的子页，只有在编辑子页时才能更改
				const curPageType = !this.isSelectMode ? this.curPageType : this.curPageTypeForPicker;
				return curPageType === 'page' && !!this.widget.subPageId;
	    },
      styles() {
        const {relateSubPageId} = this.widget;
        const widget = relateSubPageId ? WidgetFactory.getWidgetById(relateSubPageId) : this.widget;
        if (!widget || !widget.UI.state) return;
        const styles = {};
        const {backStyle = {}} = widget.getCurrentState();
        const {
          border = {},
          shadow = {},
          borderRadius = {},
          backgroundColor = '#FFFFFF',
          backgroundImage = ''
        } = backStyle

        // 基础样式
        const basicStyles = getBasicStyles(widget.getCurrentState());
        // 修改背景

        styles.backgroundColor = formatColor(backgroundColor, this.activeTheme);
        // 修改文字
        //  textStyle &&  styles.color = this.formatColor(textStyle.color);
        //修改边框
        const {
          top: bTop = {}, left: bLeft = {}, bottom: bBottom = {}, right: bRight = {}
        } = border;
        const {width: btWidth = 0, color: btColor = ''} = bTop;
        const {width: blWidth = 0, color: blColor = ''} = bLeft;
        const {width: bbWidth = 0, color: bbColor = ''} = bBottom;
        const {width: brWidth = 0, color: brColor = ''} = bRight;
        styles.borderColor = formatColor(border.color, this.activeTheme);
        btWidth && btColor && (basicStyles.borderTop = `${btWidth}px ${formatColor(btColor, this.activeTheme)} solid`)
        blWidth && blColor && (basicStyles.borderLeft = `${blWidth}px ${formatColor(blColor, this.activeTheme)} solid`);
        bbWidth && bbColor && (basicStyles.borderBottom = `${bbWidth}px ${formatColor(bbColor, this.activeTheme)} solid`);
        brWidth && brColor && (basicStyles.borderRight = `${brWidth}px ${formatColor(brColor, this.activeTheme)} solid`);
        // 修改阴影
        const {xOffset = 0, yOffset = 0, blur = 0, spread = 0, color = '', type = ''} = shadow;
        color && (basicStyles.boxShadow = `${xOffset}px ${yOffset}px ${blur}px ${spread}px ${formatColor(color, this.activeTheme)} ${type}`);
        // 背景图片
        if (backgroundImage) {
          styles.backgroundImage = `url(${assetBaseUrl}/file/download/${backgroundImage})`;
          styles.backgroundSize = 'cover';
          styles.backgroundPosition = 'center';
          styles.backgroundRepeat = 'no-repeat';
        }
        if (widget.category === 'image') {
          if (!backgroundImage) {
            styles.backgroundImage = `url(${require('@/assets/img/empty-state.png')})`;
            styles.backgroundSize = 'cover';
            styles.backgroundPosition = 'center';
            styles.backgroundRepeat = 'no-repeat';
          }
        }
        if (widget.category === 'circleClock') {
          if (!backgroundImage) {
            styles.backgroundImage = `url(${require('@/assets/img/clock.png')})`;
            styles.backgroundSize = 'cover';
            styles.backgroundPosition = 'center';
            styles.backgroundRepeat = 'no-repeat';
          }
        }
        if (widget.category === 'serviceCall') {
          if (!backgroundImage) {
            styles.backgroundImage = `url(${require('@/assets/img/serviceCall.png')})`;
            styles.backgroundSize = '100% 100%';
            styles.backgroundPosition = 'center';
            styles.backgroundRepeat = 'no-repeat';
          }
        }

        if (widget.category === 'calendar') {
          if (!backgroundImage) {
            styles.backgroundImage = `url(${require('@/assets/img/calendar.jpeg')})`;
            styles.backgroundSize = '100% 100%';
            styles.backgroundPosition = 'center';
            styles.backgroundRepeat = 'no-repeat';
          }
        }
        if (widget.category === 'qrCode') {
          if (!backgroundImage) {
            styles.backgroundImage = `url(${require('@/assets/img/qrCode.png')})`;
            styles.backgroundSize = 'contain';
            styles.backgroundPosition = 'center';
            styles.backgroundRepeat = 'no-repeat';
          }
        }
        //滚动容器
        if (widget.category === 'scroll') {
          if (widget.UI.data.scrollDirection === 'horizontal') {
            styles.overflowX = 'scroll';
            styles.overflowY = 'hidden';
          } else {
            styles.overflowY = 'scroll';
            styles.overflowX = 'hidden';
          }
        }
        // 圆角
        const {
          width: brgWidth = 0,
          topLeft = 0,
          topRight = 0,
          bottomLeft = 0,
          bottomRight = 0,
        } = borderRadius;
        if (brgWidth) {
          borderRadius.topLeft = brgWidth;
          borderRadius.topRight = brgWidth;
          borderRadius.bottomLeft = brgWidth;
          borderRadius.bottomRight = brgWidth;
        }
        topLeft && (styles.borderTopLeftRadius = `${topLeft}px`);
        topRight && (styles.borderTopRightRadius = `${topRight}px`);
        bottomLeft && (styles.borderBottomLeftRadius = `${bottomLeft}px`);
        bottomRight && (styles.borderBottomRightRadius = `${bottomRight}px`);
        return {...styles, ...basicStyles};
      },
      showMask() {
        if (this.widget.type !== 'atomic') return false;
        const containers = [
          'container', 'tabBarPage', 'scroll', 'listCell',
          'listView', 'gridView', 'buttonList','dragLayout','pageView'
        ];
        return !containers.includes(this.widget.category);
      },
    },
    watch: {
      computedWidget: {
        handler(widget) {
          if (this.isSelectMode) return;
          this.widgetChangeHandler(widget);
          // //同步子页面的显隐到主页面，必须点到主页的子页才生效
          // const {relateSubPageId} = this.widget;
          // if (relateSubPageId) {
          //   const subPage = WidgetFactory.getWidgetById(relateSubPageId);
          //   this.widget.visible= subPage.visible;
          // }
        },
        deep: true,
      },
      'widget.rect': {
        handler(rect = {}) {
          this.widget.tempRect = deepCopy(rect);
        },
        deep: true,
        immediate: true
      },

    },
    created() {
      // 注意：watch 中使用防抖动，防抖动方法需要定义在 data 中，不能写在 methods 中，
      // 因为当页面有多个 widget 实例时，会导致防抖逻辑不独立，造成防抖不能正常生效
      this.widgetChangeHandler = _.debounce((newWidget) => {
        this.widget.curHash = generateWidgetHash(newWidget);
      }, 300);
    },
    beforeDestroy() {
      this.clearSnapLineTimer();
    },
    methods: {
      onClicked() {
        if (!this.isSelectMode) {
          if (!this.widget.selectable) return;
          this.$EventBus.$emit('selectWidget', this.widget);
        } else {
          this.$EventBus.$emit('selectWidgetForPicker', this.widget);
        }
      },
      doubleClickWidget(event) {
        !this.belongNotMatch && event.stopPropagation();
        if (!this.isSelectMode || this.belongNotMatch) return;
        this.$EventBus.$emit('dbClickWidgetForPicker', this.widget);
      },
      onResize(rect = {}) {
        const {left = 0, top = 0, width = 0, height = 0} = rect;
        this.widget.tempRect = {left, top, width, height};
        this.widget.calcSnapLine();
        if (this.widget.isRoot) return;
        this.widget.calcSpaceLine();
      },
      stopResize(rect = {}) {
        // 记录组件变更前后的值，用于撤销/重做相关处理
        if (!WidgetFactory.judgeWidgetRectEqual(this.widget.rect, rect)) {
          const oldWidget = WidgetFactory.getWidgetNecessaryProperty(this.widget);
          this.widget.rect = deepCopy(rect);
          const newWidget = WidgetFactory.getWidgetNecessaryProperty(this.widget);
          WidgetFactory.undoRedoHdl.operationHdl([{
            operationType: 'edit', widgets: [{from: oldWidget, to: newWidget}]
          }]);
        }
        this.widget.hideSpaceLine();
        this.snapLineTimer = setTimeout(() => {
          this.widget.hideSnapLine();
          this.clearSnapLineTimer();
        }, 300);
      },
      clearSnapLineTimer() {
        clearTimeout(this.snapLineTimer);
        this.snapLineTimer = null;
      },
    }
  };
</script>

<style scoped lang="less">
  .snap-line {
    position: absolute;
    background: #6eb1eb;
    z-index: 999;
  }

  .snap-line-vertical {
    top: 0;
    bottom: 0;
    width: 1px;
  }

  .snap-line-horizontal {
    left: 0;
    right: 0;
    height: 1px;
  }

  // 垂直、水平间距线
  .space-line {
    background: white;
    z-index: 999;
    position: absolute;
  }

  .space-line.space-line-vertical {
    width: 1px;
  }

  .space-line.space-line-horizontal {
    height: 1px;
  }

  .widget-mask {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
  }

  .widget-select-mark {
    position: absolute;
    top: 1px;
    right: 1px;
    font-size: 12px;
    font-weight: bold;
    z-index: 99;
  }

  .el-divider__text {
    padding: 0 1px;
  }

  .el-divider__text.is-center.ver-center {
    top: 50%;
  }
</style>
